package com.aeon.profiler;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

import javassist.ByteArrayClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

public class Transformer implements ClassFileTransformer {
	private Instrumentation mInstrumentation;
	private ClassPool mClassPool;

	public Transformer(Instrumentation inst) {
		mInstrumentation = inst;
		mClassPool = ClassPool.getDefault();
	}

	@Override
	public byte[] transform(ClassLoader loader, String className,
			Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
			byte[] classfileBuffer) throws IllegalClassFormatException {
		 
//		System.out.println(className + " intransformer");
		return transform0(loader, className, classBeingRedefined,
				protectionDomain, classfileBuffer);

	}

	private byte[] transform0(ClassLoader loader, String className,
			Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
			byte[] classfileBuffer) throws IllegalClassFormatException {

		try {
			if (!isAppCode(className.replace("/", "."))) {
				return classfileBuffer;
			}
			// pass bytes to pool to create class text
			mClassPool.insertClassPath(new ByteArrayClassPath(className,
					classfileBuffer));
			// get class text
			CtClass ctClass = mClassPool.get(className.replace("/", "."));
			CtMethod[] ctMethods = ctClass.getDeclaredMethods();

			for (CtMethod method : ctMethods) {
				// System.out.println(method.getName());
				// if(!(method.getDeclaringClass().getName().contains(className))){
				// continue;
				// }
				String str = "com.aeon.profiler.TimeProfile.start(\""
						+ className.replace("/", ".") + "\",\""
						+ method.getName() + "\");";
				// System.out.println(str);
				method.insertBefore(str);
				method.insertAfter("com.aeon.profiler.TimeProfile.end(\""
						+ className.replace("/", ".") + "\",\""
						+ method.getName() + "\");");
			}
			byte[] bs = ctClass.toBytecode();
			return bs;
		} catch (Throwable throwable) {
			throwable.printStackTrace();
		}
		// System.out.println("at the end of transformer");
		return classfileBuffer;
	}

	private boolean isAppCode(String namespace) {
		if (namespace.startsWith("java") || namespace.contains("sun")
				|| namespace.startsWith("com.sun.org")
				|| namespace.contains("com.aeon.profiler")
				|| namespace.contains("javassist")
				|| namespace.startsWith("org")||namespace.startsWith("ch.qos")) {
			return false;
		}
//		if(namespace.contains("com.teamcenter.")||namespace.contains("com.aeon.")){return true;}
		return true;
	}
}
